package com.uobgroup.ews.uam.web;

import java.io.UnsupportedEncodingException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.util.UriUtils;
import org.springframework.web.util.WebUtils;

import com.google.gson.Gson;
import com.uobgroup.ews.uam.core.dao.ldap.LDSDaoImpl;
import com.uobgroup.ews.uam.core.domain.Reference;
import com.uobgroup.ews.uam.core.domain.RoleSubType;
import com.uobgroup.ews.uam.core.domain.UAMRole;
import com.uobgroup.ews.uam.core.model.Group;
import com.uobgroup.ews.uam.core.service.ReferenceService;
import com.uobgroup.ews.uam.core.service.RoleSubTypeService;
import com.uobgroup.ews.uam.core.service.SecurityGroupService;
import com.uobgroup.ews.uam.core.service.UAMRoleService;
import com.uobgroup.ews.uam.core.service.ldap.LDSServiceImpl;
import com.uobgroup.ews.uam.web.dto.ProfileJsonItem;
import com.uobgroup.ews.uam.web.dto.ProfileJsonObject;

@RequestMapping("/uamroles")
@Controller
public class UAMRoleController {

   @Autowired
   private ReferenceService referenceService;

   @Autowired
   private UAMRoleService uamRoleService;

   @Autowired
   private SecurityGroupService securityGroupService;

   @Autowired
   private ReloadableResourceBundleMessageSource messageSource;

   @Autowired
   private RoleSubTypeService roleSubTypeService;

   @Autowired
   private LDSServiceImpl lDsService;

   @RequestMapping(method = RequestMethod.POST, produces = "text/html")
   public String create(@Valid UAMRole uamRole, BindingResult bindingResult, Model uiModel,
         HttpServletRequest httpServletRequest, Principal principal) {
      if (bindingResult.hasErrors()) {
         populateEditForm(uiModel, uamRole, null, "");
         return "uamroles/create";
      }
      Group group = lDsService.findGroupByBaseDN(uamRole.getName().trim(), LDSDaoImpl.LDAP_DN_GROUP_ROLES);
      if (!uamRoleService.IsExistSecurityGroup(uamRole) && null == group) {
         uiModel.asMap().clear();
         uamRole.setLastModificationUserId(principal.getName());
         uamRoleService.saveUAMRole(uamRole);
         return "redirect:/uamroles/view/" + encodeUrlPathSegment(uamRole.getId().toString(), httpServletRequest);
      }
      else {
         populateEditForm(uiModel, uamRole, null, messageSource.getMessage("security_group_exist", null, null));
         return "uamroles/create";
      }
   }

   @RequestMapping(value = "/create", produces = "text/html")
   public String createForm(Model uiModel) {
      populateEditForm(uiModel, new UAMRole(), null, "");
      return "uamroles/create";
   }

   @RequestMapping(value = "/view/{id}", produces = "text/html")
   public String show(@PathVariable("id") Long id, Model uiModel) {
      uiModel.addAttribute("uamrole_", uamRoleService.findUAMRole(id));
      uiModel.addAttribute("itemId", id);
      return "uamroles/show";
   }

   @RequestMapping(produces = "text/html")
   public String list(@RequestParam(value = "page", required = false) Integer page,
         @RequestParam(value = "size", required = false) Integer size, Model uiModel, @ModelAttribute("error") final String error) {
      // if (page != null || size != null) {
      int sizeNo = size == null ? 10 : size.intValue();
      final int firstResult = page == null ? 0 : (page.intValue() - 1) * sizeNo;
      uiModel.addAttribute("uamroles", uamRoleService.findUAMRoleEntries(firstResult, sizeNo));
      float nrOfPages = (float) uamRoleService.countAllUAMRoles() / sizeNo;
      uiModel.addAttribute("maxPages", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1
            : nrOfPages));
      /*
       * } else {
       * 
       * uiModel.addAttribute("uamroles", uamRoleService.findAllUAMRoles()); }
       */

      // if(error != null)
      uiModel.addAttribute("message", error);
      return "uamroles/list";
   }

   @RequestMapping(method = RequestMethod.PUT, produces = "text/html")
   public String update(@Valid UAMRole uamRole, BindingResult bindingResult, Model uiModel,
         HttpServletRequest httpServletRequest, Principal principal, final RedirectAttributes redirectAttrs) {
      UAMRole u1 = uamRoleService.findUAMRole(uamRole.getId());
      if (null == u1) {
         redirectAttrs.addFlashAttribute("error", messageSource.getMessage("entity_not_found_single", new String[] {messageSource.getMessage("label_com_uobgroup_ews_uam_core_domain_uamrole", null, null)}, null));
         redirectAttrs.addAttribute("page", "1");
         redirectAttrs.addAttribute("size", "10");
         return "redirect:/uamroles";
      }
      if (bindingResult.hasErrors()) {
         populateEditForm(uiModel, uamRole, null, "");
         return "uamroles/update";
      }

      uiModel.asMap().clear();
      uamRole.setLastModificationUserId(principal.getName());
      if (uamRole.getSecurityGroup() != null) {
         uamRole.setSecurityGroup(securityGroupService.findSecurityGroup(uamRole.getSecurityGroup().getId()));
      }
      uamRoleService.updateUAMRole(uamRole);
      return "redirect:/uamroles/view/" + encodeUrlPathSegment(uamRole.getId().toString(), httpServletRequest);
   }

   @RequestMapping(value = "/update/{id}", produces = "text/html")
   public String updateForm(@PathVariable("id") Long id, Model uiModel, final RedirectAttributes redirectAttrs) {
      UAMRole uamRole = uamRoleService.findUAMRole(id);
      if (null == uamRole) {
         redirectAttrs.addFlashAttribute("error", messageSource.getMessage("entity_not_found_single", new String[] {messageSource.getMessage("label_com_uobgroup_ews_uam_core_domain_uamrole", null, null)}, null));
         redirectAttrs.addAttribute("page", "1");
         redirectAttrs.addAttribute("size", "10");
         return "redirect:/uamroles";
      }
      populateEditForm(uiModel, uamRole, uamRole.getRoleType(), "");
      return "uamroles/update";
   }

   @RequestMapping(value = "/{id}", method = RequestMethod.DELETE, produces = "text/html")
   public String delete(@PathVariable("id") Long id, @RequestParam(value = "page", required = false) Integer page,
         @RequestParam(value = "size", required = false) Integer size, Model uiModel, Principal principal,
         final RedirectAttributes redirectAttrs) {
      uiModel.asMap().clear();
      UAMRole uamRole = uamRoleService.findUAMRole(id);
      // String message = "";
      // String errorMessageKey = null;
      if (null == uamRole) {
         redirectAttrs.addFlashAttribute("error", messageSource.getMessage("entity_not_found_single",
               new String[] { messageSource.getMessage("label_com_uobgroup_ews_uam_core_domain_uamrole", null, null) },
               null));
      }
      else {
         try {
            if (!uamRoleService.IsAssignProfile(id)) {
               uamRole.setLastModificationUserId(principal.getName());
               uamRoleService.deleteUAMRole(uamRole);
            }
            else {
               redirectAttrs.addFlashAttribute("error",
                     messageSource.getMessage("role_is_assigned_to_profile", null, null));
            }
         }
         catch (Exception e) {
            redirectAttrs.addFlashAttribute("error", messageSource.getMessage("field_cannot_delete", null, null));
         }
         /*
          * if (errorMessageKey != null) { uiModel.addAttribute("messageError",
          * messageSource.getMessage(errorMessageKey, new String[] {
          * uamRole.getName() }, "CannotDeleteObjectException", null)); }
          */
      }

      redirectAttrs.addAttribute("page", (page == null) ? "1" : page.toString());
      redirectAttrs.addAttribute("size", (size == null) ? "10" : size.toString());

      return "redirect:/uamroles";
   }

   private void populateEditForm(Model uiModel, UAMRole uamRole, Reference ref, String message) {

      uiModel.addAttribute("UAMRole_", uamRole);
      com.uobgroup.ews.uam.core.domain.Reference refFirstRoleType = null;

      if (ref == null) {
         refFirstRoleType = referenceService.findFirstReferenceRoleType();
         if (refFirstRoleType != null)
            uiModel.addAttribute("roleSubTypes", roleSubTypeService.findByRoleTypeID(refFirstRoleType.getId()));
      }
      else
         uiModel.addAttribute("roleSubTypes", roleSubTypeService.findByRoleTypeID(ref.getId()));

      uiModel.addAttribute("roletypes", referenceService.findAllRoleType());

      uiModel.addAttribute("processingcentres", referenceService.findAllProcessingCenters());
      uiModel.addAttribute("departments", referenceService.findAllDepartments());

      if (message != "")
         uiModel.addAttribute("message", messageSource.getMessage("security_group_exist", null, null));
      else
         uiModel.addAttribute("message", "");

   }

   @RequestMapping(method = RequestMethod.GET, value = "/populateRoleSubType/{id}", headers = "Accept=application/json")
   public @ResponseBody
   String getRoleSubType(@PathVariable("id") String id) {

      List<RoleSubType> list = new ArrayList<RoleSubType>();

      list = roleSubTypeService.findByRoleTypeID(Long.parseLong(id));

      ProfileJsonObject obj = new ProfileJsonObject();
      obj.setIdentifier("id");
      obj.setLabel("name");
      List<ProfileJsonItem> items = new ArrayList<ProfileJsonItem>();

      for (RoleSubType roleSubType : list) {
         items.add(new ProfileJsonItem(roleSubType.getId(), roleSubType.getName()));
      }
      obj.setItems(items);
      Gson gson = new Gson();
      return gson.toJson(obj);
   }

   private String encodeUrlPathSegment(String pathSegment, HttpServletRequest httpServletRequest) {
      String enc = httpServletRequest.getCharacterEncoding();
      if (enc == null) {
         enc = WebUtils.DEFAULT_CHARACTER_ENCODING;
      }
      try {
         pathSegment = UriUtils.encodePathSegment(pathSegment, enc);
      }
      catch (UnsupportedEncodingException uee) {
      }
      return pathSegment;
   }
}
